package com.graduate.framework.utils;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.graduate.framework.exception.WeBaseFrontException;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.List;

/**
 * webase-front工具类
 *
 * @author: qhx20040819
 * @date: 2023-10-20 14:20
 **/

@Component
@Slf4j
public class WeBaseFrontUtils
{

    @Value("${contract.url}")
    public String URL;
    @Value("${contract.address}")
    public String CONTRACT_ADDRESS;
    @Value("${contract.name}")
    public String CONTRACT_NAME;
    @Value("${contract.abi}")
    public String CONTRACT_ABI;
    @Value("${contract.owner}")
    public String OWNER;
    private int wei = 2; // 小数 -> 区块链网络数字 转换位数

    public String contractRequest(String userAddress, String funcName, List<Object> params)
    {
        JSONObject requestBody = new JSONObject();
        requestBody.putOpt("contractName", CONTRACT_NAME);
        requestBody.putOpt("contractAddress", CONTRACT_ADDRESS);
        requestBody.putOpt("contractAbi", JSONUtil.parseArray(CONTRACT_ABI));
        requestBody.putOpt("user", "");
        requestBody.putOpt("funcName", funcName);
        requestBody.putOpt("funcParam", params);
        requestBody.putOpt("user", userAddress);
        return httpPost(requestBody.toString());
    }

    public JSONArray call(String userAddress, String funcName, List<Object> params)
    {
        String response = contractRequest(userAddress, funcName, params);
        try
        {
            JSONArray resJson = JSONUtil.parseArray(response);
            return resJson;
        } catch (Exception e)
        {
            throw new WeBaseFrontException(e);
        }
    }

    public JSONArray call(String funcName, List<Object> params)
    {
        return call(OWNER, funcName, params);
    }

    public String sendTransaction(String userAddress, String funcName, List<Object> params)
    {
        String response = contractRequest(userAddress, funcName, params);
        try
        {
            JSONObject resJson = JSONUtil.parseObj(response);
            if (resJson.getBool("statusOK"))
            {
                return null;
            } else
            {
                return resJson.getStr("message");
            }
        } catch (Exception e)
        {
            throw new WeBaseFrontException(e);
        }
    }

    public String sendTransaction(String funcName, List<Object> params)
    {
        return sendTransaction(OWNER, funcName, params);
    }


    /**
     * 将 BigDecimal 转换为 int
     *
     * @param bigDecimal
     * @return 100.28 -> 10028
     */
    public int bigDecimalToUint(BigDecimal bigDecimal)
    {
        return bigDecimal.multiply(
                new BigDecimal(Math.pow(10, wei))
        ).intValue();
    }

    /**
     * 将 int 转换为 BigDecimal
     *
     * @param intValue
     * @return 10028 -> 100.28
     */
    public BigDecimal uintToBigDecimal(int intValue)
    {
        // 用Math库实现10的二次方
        BigDecimal bigDecimal = new BigDecimal(Math.pow(10, wei));
        return new BigDecimal(intValue).divide(bigDecimal, wei, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 发送 post 请求
     *
     * @param jsonStr Form表单json字符串
     * @return 请求结果
     */
    private String httpPost(String jsonStr)
    {
        // 创建httpClient
        CloseableHttpClient httpClient = HttpClients.createDefault();
        // 创建post请求方式实例
        HttpPost httpPost = new HttpPost(URL);
        // 设置请求头 发送的是json数据格式
        httpPost.setHeader("Content-type", "application/json;charset=utf-8");
        // 设置参数---设置消息实体 也就是携带的数据
        StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));
        // 设置编码格式
        entity.setContentEncoding("UTF-8");
        // 发送Json格式的数据请求
        entity.setContentType("application/json");
        // 把请求消息实体塞进去
        httpPost.setEntity(entity);
        // 执行http的post请求
        CloseableHttpResponse httpResponse;
        String result = null;
        try
        {
            httpResponse = httpClient.execute(httpPost);
            result = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
        } catch (IOException e)
        {
            e.printStackTrace();
        }
        return result;
    }

}
